﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Krile.Kernel;
using Krile.Kernel.Control;
using Krile.Kernel.Control.Surface;
using Krile.Kernel.Control.Surface.MessageObjects;
using Krile.Common;
using System.Net;
using System.Text.RegularExpressions;

namespace Highkick.Common
{
    public static class XStringGenerator
    {
        public static XString CreateXString(this string text, string replyToId)
        {
            XString xs = new Krile.Kernel.Control.XString();
            xs.Original = text;
            if (!String.IsNullOrEmpty(replyToId))
                xs.HeaderText = "@" + replyToId;
            var texts = text.Replace("\r", "").Split(new[] { "\n" }, StringSplitOptions.None);
            List<MessageObject> msgobj = new List<MessageObject>();
            foreach(var t in texts)
            {
                msgobj.AddRange(CreateMsgObjects(t));
                msgobj.Add(new Newline());
            }
            xs.MessageObjects = msgobj.ToArray();
            return xs;
        }

        static Regex idRegex = new Regex(@"(id:[A-Za-z0-9_]*)", RegexOptions.Singleline | RegexOptions.Compiled);
        static MessageObject[] CreateMsgObjects(string msg)
        {
            msg = msg.Replace("&", "&amp;").Replace("<", "&lt;").Replace(">", "&gt;").Replace("\r", "").Replace("\n", " ");
            //pre-processor
            msg = Krile.Common.Regexs.URLRegex.Replace(msg, "<$1>$1<");
            msg = Krile.Common.Regexs.AtRegex.Replace(msg, "@<" + "http://h.hatena.ne.jp/" + "$1>$1<");
            msg = idRegex.Replace(msg, "<" + "http://h.hatena.ne.jp/" + "$1>id:$1<");
            List<MessageObject> objStock = new List<MessageObject>();
            foreach (var item in msg.Split(new[] { '<' }, StringSplitOptions.RemoveEmptyEntries))
            {
                if (item.Contains('>'))
                {
                    var iArray = item.Split('>');
                    //link
                    if (Uri.IsWellFormedUriString(iArray[0].Replace("&lt;", "<").Replace("&gt;", ">").Replace("&amp;", "&"), UriKind.RelativeOrAbsolute))
                    {
                        try
                        {
                            string origstr = iArray[0].Replace("&lt;", "<").Replace("&gt;", ">").Replace("&amp;", "&");
                            if (origstr.StartsWith("http://h.hatena.ne.jp/"))
                            {
                                objStock.Add(new Hyperlink(origstr, iArray[1].Replace("&lt;", "<").Replace("&gt;", ">").Replace("&amp;", "&")));
                            }
                            else
                            {
                                Uri target = new Uri(origstr);
                                objStock.Add(new Hyperlink(origstr, origstr));
                                var img = GetImage(origstr);
                                if (img != null)
                                    objStock.Add(img);
                            }
                            continue;
                        }
                        catch (UriFormatException)
                        {
                            objStock.Add(new Text(item.Replace("&lt;", "<").Replace("&gt;", ">").Replace("&amp;", "&"), System.Drawing.Color.Gray));
                        }
                    }
                    break;
                }
                objStock.Add(new Text(item.Replace("&lt;", "<").Replace("&gt;", ">").Replace("&amp;", "&")));
            }
            return objStock.ToArray();
        }

        private static Image GetImage(string url)
        {
            //and png jpg bmp gif
            if (url.EndsWith(".png") ||
                url.EndsWith(".jpg") || url.EndsWith(".jpeg") || url.EndsWith(".jpe") ||
                url.EndsWith(".bmp") || url.EndsWith(".dib") ||
                url.EndsWith("gif"))
            {
                try
                {
                    return new Image(new Uri(url));
                }
                catch (UriFormatException)
                {
                    return null;
                }
            }
            else if (url.StartsWith("http://f.hatena.ne.jp/"))
            {
                //hatena fotolife
                //http://f.hatena.ne.jp/userid/YYYYMMDDhhmmss
                //http://img.f.hatena.ne.jp/images/fotolife/u[userid[0]]/userid/YYYYMMDD/YYYYMMDDhhmmss.(jpg|png)
                var splits = url.Split(new[] { '/' });
                if (splits.Length == 5)
                {
                    long val;
                    if (long.TryParse(splits[4], out val))
                    {
                        //callback url is:
                        var un = splits[3];
                        var id = splits[4];
                        if (String.IsNullOrEmpty(un) || String.IsNullOrEmpty(id) || id.Length != 14)
                            return null;
                        var callback = "http://img.f.hatena.ne.jp/images/fotolife/" + un[0] + "/" + un + "/" + id.Substring(0, 8) + "/" + id + ".jpg";
                        var callback2 = "http://img.f.hatena.ne.jp/images/fotolife/" + un[0] + "/" + un + "/" + id.Substring(0, 8) + "/" + id + ".png";
                        try
                        {
                            try
                            {
                                if ((int)GetStatusCode(callback) < 400)
                                {
                                    return new Image(new Uri(callback));
                                }
                            }
                            catch { }
                            return new Image(new Uri(callback2));
                        }
                        catch (UriFormatException)
                        {
                            return null;
                        }
                    }
                }
            }
            return null;
        }

        static public HttpStatusCode GetStatusCode(string url)
        {
            var nc = new Krile.Common.NetConnect();

            HttpWebRequest req = (HttpWebRequest)nc.CreateRequest(new Uri(url), false);
            HttpWebResponse res = null;
            HttpStatusCode statusCode;

            try
            {
                res = (HttpWebResponse)req.GetResponse();
                statusCode = res.StatusCode;

            }
            catch (WebException ex)
            {

                res = (HttpWebResponse)ex.Response;

                if (res != null)
                {
                    statusCode = res.StatusCode;
                }
                else
                {
                    throw; // サーバ接続不可などの場合は再スロー
                }
            }
            finally
            {
                if (res != null)
                {
                    res.Close();
                }
            }
            return statusCode;
        }
    }
}
